#include "mpvplayer.h"
#include "util.h"
#include <QWidget>

static void wakeup(void* ctx)
{
    MpvPlayer* mpv = (MpvPlayer*)ctx;
    emit mpv->mpvEvents();
}

MpvPlayer::MpvPlayer(QWidget* videoRenderWnd, QObject *parent)
    : QObject{parent}
{
    // 设置程序区域
    // LC_NUMERIC: 设置数字格式(包括小数点和千分位符)
    // "C": 表示使用C标准的默认区域
    std::setlocale(LC_NUMERIC, "C");

    // 创建mpv实例
    mpv = mpv_create();
    if(mpv == nullptr)
    {
        LOG() << "mpv实例创建失败";
        return;
    }

    // 设置视频渲染窗口--将窗口的id告诉给mpv
    int64_t wid = videoRenderWnd->winId();
    mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);

    // 订阅time-pos属性
    mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_INT64);

    // 设置mpv事件触发时的回调函数
    mpv_set_wakeup_callback(mpv, wakeup, this);

    connect(this, &MpvPlayer::mpvEvents, this, &MpvPlayer::onMpvEvents);

    // 初始化mpv实例
    if(mpv_initialize(mpv) < 0)
    {
        LOG() << "mpv初始化失败";
        mpv_destroy(mpv);
        return;
    }
}

MpvPlayer::~MpvPlayer()
{
    if(mpv)
    {
        mpv_terminate_destroy(mpv);
    }
}

void MpvPlayer::handleMpvEvent(mpv_event *event)
{
    switch (event->event_id)
    {
        case MPV_EVENT_PROPERTY_CHANGE:
        {
            // 属性发生变化的事件
            mpv_event_property* eventProperty = (mpv_event_property*)event->data;
            if(nullptr == eventProperty->data)
            {
                return;
            }
            if(0 == strcmp(eventProperty->name, "time-pos"))
            {
                // time-pos 属性发生改变
                int64_t seconds = *((int64_t*)eventProperty->data);
                // 发生信号
                emit playPositionChanged(seconds);
            }
            break;
        }
        case MPV_EVENT_SHUTDOWN:
        {
            mpv_terminate_destroy(mpv);
            mpv = nullptr;
            break;
        }
        default:
            break;
    }
}

void MpvPlayer::startPlay(const QString &videoPath)
{
    const QByteArray fileName = videoPath.toLocal8Bit();
    const char* args[] = {"loadfile", fileName.data(), NULL};
    mpv_command_async(mpv, 0, args);
}

void MpvPlayer::play()
{
    int pause = 0;
    mpv_set_property_async(mpv, 0, "pause", MPV_FORMAT_FLAG, &pause);
}

void MpvPlayer::pause()
{
    int pause = 1;
    mpv_set_property_async(mpv, 0, "pause", MPV_FORMAT_FLAG, &pause);
}

void MpvPlayer::setPlaySpeed(double speed)
{
    mpv_set_property_async(mpv, 0, "speed", MPV_FORMAT_DOUBLE, &speed);
}

void MpvPlayer::setMute(bool isMute)
{
    int flag = isMute ? 1 : 0;
    mpv_set_property_async(mpv, 0, "mute", MPV_FORMAT_FLAG, &flag);
}

void MpvPlayer::setVolume(int64_t volume)
{
    mpv_set_property_async(mpv, 0, "volume", MPV_FORMAT_INT64, &volume);
}

void MpvPlayer::setCurrentPlayPosition(int64_t seconds)
{
    mpv_set_property_async(mpv, 0, "time-pos", MPV_FORMAT_INT64, &seconds);
}

void MpvPlayer::onMpvEvents()
{
    // 循环处理所有事件，知道mpv事件队列为空
    while(mpv)
    {
        mpv_event* event = mpv_wait_event(mpv, 0);
        if(event->event_id == MPV_EVENT_NONE)
        {
            break;
        }

        // 获取到具体事件
        handleMpvEvent(event);
    }
}
